<template>
  <div>
    <el-upload
      id="picker"
      style="width:280px"
      drag
      action="http://10.10.10.11:9006/file/upload"
      :auto-upload="false"
      :limit="1"
    >
      <i class="el-icon-upload" />
      <div class="el-upload__text"><em>点击上传</em></div>
    </el-upload>
    <div id="picker" class="el-upload__text">
      <i class="el-icon-upload" />
      <em>点击上传</em></div>
    <ul class="file-list">
      <li v-if="fileList[0]" class="list">
        <span>{{ fileList[0].name }}</span>
        <span>进度：{{ fileList[0].percentage + '%' }}</span>
      </li>
    </ul>
  </div>
</template>

<script type="text/ecmascript-6">
import WebUploader from 'webuploader'

const request = {
  url_file_getUploadinfo: '/dev-api/chunk/md5',
  url_file_judgeFileChunkExisted: '/dev-api/chunk/check',
  url_file_uploadChunks2Server: '/dev-api/chunk/upload',
  url_file_completeUpload2Server: '/dev-api/chunk/merge',

  arg_file_getUploadinfo: {
    md5: '',
    fileName: '',
    directoryId: '',
    fileSizeStr: '',
    folderId: ''
  },
  arg_file_judgeFileChunkExisted: {
    md5: '',
    chunkMd5: ''
  },
  arg_file_uploadChunks2Server: {
    objectId: '',
    file: '',
    md5: '',
    chunkMd5: '',
    chunkSizeStr: '',
    chunkIndexStr: '',
    fileName: ''
  },
  arg_file_completeUpload2Server: {
    objectId: '',
    fileName: '',
    fileSizeStr: '',
    md5: '',
    directoryId: '',
    folderId: '',
    chunksCountStr: ''
  }

}

export default {
  name: 'HelloWorld',
  data() {
    return {
      options: {
        auto: true,
        url: request.url_file_uploadChunks2Server,
        button: '#picker',
        multiple: true,
        accept: '*',
        threads: 1,
        fileNumLimit: 3,
        formData: request.arg_file_uploadChunks2Server,
        chunked: true,
        chunkSize: 5 * 1024 * 1024,
        duplicate: true
      },
      file: {},
      fileList: [],
      uniqueName: null
    }
  },
  mounted() {
    this.registerWebUpload()
    this.initWebUpload()
  },
  methods: {
    registerWebUpload() {
      const $this = this
      WebUploader.Uploader.register({
        'before-send-file': 'beforeSendFile',
        'before-send': 'beforeSend',
        'after-send-file': 'afterSendFile'
      }, {
        // 时间点1：所有分块进行上传之前调用此函数
        beforeSendFile: function(file) {
          const deferred = WebUploader.Deferred()
          const uploader = this;
          (new WebUploader.Uploader()).md5File(file)
            .then(md5 => {
              // 判断文件是否存在
              $this.$post(request.url_file_getUploadinfo, {
                md5: md5,
                // fileName: file.name,
                // fileSizeStr: file.size.toString(),
                // directoryId: 58,
                folderId: -1
              })
                .then(json => {
                  // console.log(json)
                  // console.log(json.data.code)
                  // if (json.success && json.code === '200') { // 文件不存在
                  if (json.data.code === 400) { // 文件不存在
                    $this.file = {
                      file,
                      // 拿到上传文件的唯一名称，用于断点续传  需要确保前后端的md5算法和参数一致
                      uniqueName: md5,
                      md5: md5,
                      fileName: file.name,
                      fileSizeStr: Number(file.size.toString()),
                      objectId: json.data.objectId,
                      directoryId: 58,
                      folderId: 58
                    }
                    deferred.resolve()
                  } else if (json.success && json.code === '013') { // 文件存在
                    file.setStatus('complete')
                    uploader.owner.skipFile(file)
                    deferred.resolve()
                  } else {
                    deferred.reject()
                  }
                })
            })
          return deferred.promise()
        },
        // 时间点2：如果有分块上传，则每个分块上传之前调用此函数
        beforeSend: (block) => {
          const deferred = WebUploader.Deferred()
          const file = block.file; // 获取分片所属的文件对象
          (new WebUploader.Uploader()).md5File(file)
            .then(md5 => {
              // 判断分块是否存在
              // const getData = Object.assign({}, {
              //   chunkIndex: 1,
              //   name: '8992d9234166eed224c5176fa4beb86d',
              //   size: 5120000
              //   // md5: this.file.md5,
              //   // chunkMd5: md5,
              //   // objectId: this.file.objectId
              // })
              this.$postJson(request.url_file_judgeFileChunkExisted, {
                chunkIndex: block.chunk.toString(),
                name: md5,
                size: file.size.toString()
              }).then(json => {
                this.file = Object.assign(this.file, {
                  // file,
                  chunkMd5: md5,
                  chunkSizeStr: file.size.toString(),
                  chunkIndexStr: block.chunk.toString()
                })
                this.uploader.options.formData = this.file
                if (json.code === '200') {
                  if (json.data) { // 块存在
                    deferred.reject()
                    this.file.file = ''
                  } else {
                    deferred.resolve()
                  }
                } else {
                  // 上传失败，重新上传分块内容
                  deferred.resolve()
                }
              })
            })

          return deferred.promise()
        },
        // 时间点3：上传完成
        afterSendFile: (file, ret) => {
          const deferred = WebUploader.Deferred()
          // 不是秒传，走完成接口
          if (this.file.md5) {
            // 开始构造后台所需要的参数
            const getData = Object.assign({}, {
              // chunks: 2
              contextType: this.file.file.type,
              ext: this.file.ext || 'exe',
              submittedFileName: this.file.fileName,
              // objectId: this.file.objectId,
              name: 'bdee2e9768febc413b43d287f93e81c8' || this.file.chunkMd5,
              // name: this.file.uniqueName,
              size: Number(this.file.chunkSizeStr),
              md5: this.file.md5,
              folderId: -1 || this.file.folderId,
              chunks: Math.ceil(file.size / this.options.chunkSize)
            })
            this.$postJson(request.url_file_completeUpload2Server, getData)
              .then(json => {
                if (json.data.code === 200) {
                  this.$message.success('上传成功')
                  this.$emit('setFileUrl', json.data.data.data.url)
                  deferred.resolve()
                } else {
                  // this.$message.success('上传失败')
                  deferred.reject()
                }
              })
          } else { // 秒传
            deferred.resolve()
          }

          return deferred.promise()
        }
      })
    },
    initWebUpload() {
      const options = this.options
      const $this = this

      this.uploader = WebUploader.create({
        auto: options.auto,
        swf: '../assets/lib/webuploader/Uploader.swf',
        // swf: '',
        server: options.url,
        // pick: {
        //   id: options.button,
        //   multiple: options.multiple,
        //   label: '选择文件'
        // },
        pick: options.button,
        accept: options.accept,
        threads: options.threads,
        fileNumLimit: options.fileNumLimit,
        formData: options.formData,
        chunked: options.chunked,
        chunkSize: options.chunkSize,
        chunkRetry: 1,
        duplicate: options.duplicate,
        prepareNextFile: false
      })

      // 当有文件被添加进队列的时候，添加到页面预览
      this.uploader.on('fileQueued', (file) => {
        // this.$emit('fileChange', file);
        $this.fileList.push(file)
      })

      this.uploader.on('uploadStart', (file) => {
        // 在这里可以准备好formData的数据
        // this.uploader.options.formData.key = this.keyGenerator(file);
      })

      this.uploader.on('startUpload', (file) => {
        // 开始一次上传
        // this.fileList = [];
      })

      // 文件上传过程中创建进度条实时显示。
      this.uploader.on('uploadProgress', (file, percentage) => {
        this.$emit('progress', file, percentage)
        $this.fileList.forEach((item, index) => {
          if (item.id === file.id) {
            item.percentage = percentage * 100
            $this.fileList.splice(index, 1, item)
            return
          }
        })
      })
      this.uploader.on('uploadSuccess', (file, response) => {
        this.$emit('success', file, response)
        $this.fileList.forEach((item, index) => {
          if (item.id === file.id) {
            item.percentage = 100
            $this.fileList.splice(index, 1, item)
            return
          }
        })
      })

      this.uploader.on('uploadError', (file, reason) => {
        // console.error(reason);
        // this.$emit('uploadError', file, reason);
      })

      this.uploader.on('error', (type) => {
        let errorMessage = ''
        if (type === 'F_EXCEED_SIZE') {
          errorMessage = `文件大小不能超过${this.fileSingleSizeLimit / (1024 * 1000)}M`
        } else if (type === 'Q_EXCEED_NUM_LIMIT') {
          errorMessage = '文件上传已达到最大上限数'
        } else {
          errorMessage = `上传出错！请检查后重新上传！错误代码${type}`
        }
        console.error(errorMessage)
        // this.$emit('error', errorMessage);
      })

      this.uploader.on('uploadComplete', (file, response) => {
        this.$emit('complete', file, response)
      })

      this.uploader.on('uploadFinished', () => {
        // 所有文件上传结束
        // 重置文件队列
        this.uploader.reset()
      })
    },
    upload(file) {
      this.uploader.upload(file)
    },
    stop(file) {
      this.uploader.stop(file)
    },
    // 取消并中断文件上传
    cancelFile(file) {
      this.uploader.cancelFile(file)
    },
    // 在队列中移除文件
    removeFile(file, bool) {
      this.uploader.removeFile(file, bool)
    },
    getAccept(accept) {
      switch (accept) {
        case 'text':
          return {
            title: 'Texts',
            exteensions: 'doc,docx,xls,xlsx,ppt,pptx,pdf,txt',
            mimeTypes: '.doc,docx,.xls,.xlsx,.ppt,.pptx,.pdf,.txt'
          }
          // eslint-disable-next-line no-unreachable
          break
        case 'video':
          return {
            title: 'Videos',
            exteensions: 'mp4',
            mimeTypes: '.mp4'
          }
          // eslint-disable-next-line no-unreachable
          break
        case 'image':
          return {
            title: 'Images',
            exteensions: 'gif,jpg,jpeg,bmp,png',
            mimeTypes: '.gif,.jpg,.jpeg,.bmp,.png'
          }
          // eslint-disable-next-line no-unreachable
          break
        default:
          return accept
      }
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
  #picker {
    display: inline-block;
    width: 100px;
    /* padding: 7px 10px; */
    border: 1px solid;
    /* background: #0099CC; */
    border-radius: 3px;
    color: #fff;
    font-size: 7px;
  }

  #picker input {
    display: none;
  }
</style>
